<?php
/**
 * Class template and factory provider for extractor classes which can extract
 * text from files and use it to produce Marjory_Document objects.
 */
abstract class Marjory_Document_Extractor
{
    protected $filePath;

    public static $mimeMap = array(
        'text/html' => 'Marjory_Document_Extractor_Html',
        'text/xml'  => 'Marjory_Document_Extractor_Xml',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'Marjory_Document_Extractor_Docx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'Marjory_Document_Extractor_Xlsx',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'Marjory_Document_Extrator_Pptx',
        'application/msword' => 'Marjory_Document_Extrator_Office97',
        '' => '',
        '' => '',
        '' => '',
        '' => '',
        '' => '',

    );

    /**
     * Constructor for extractor object. 
     *
     * @param string $filePath
     */
    public function __construct($filePath)
    {
        $this->filePath = $filePath;
    }

    /**
     * Extracts a Marjory_Document from a file found at the given $filePath.
     * Will throw exception if the extraction process fails.
     *
     * @param string $filePath
     * @return Marjory_Document
     * @throws Marjory_Exception
     */
    public function extract()
    {
        throw new Marjory_Exception(get_class($this).'::extract() has not yet been implemented');
    }

    /**
     * Factory method. Chooses suitable extractor according to the given file's
     * mimetype and the extractor class defined for that mimetype. Class files
     * must be loadable using autoload.
     * Requires the fileinfo extension to be installed!
     * Takes the filename as the parameter, and performs sanity checks (e.g.,
     * see if the file exists and is readable). Will throw an exception if sanity
     * checks are not satisfied, fileinfo extension is not present, or configured
     * extractor class can not be found.
     *
     * @param string $filePath
     * @return mixed Marjory_Document_Extractor instance or false if no extractor has been configured for the given mimetype.
     * @throws Marjory_Exception
     */
    final public static function factory($filePath)
    {
        if (!file_exists($filePath) || !is_file($filePath) || !is_readable($filePath)) {
            throw new Marjory_Exception("File '$filePath' does not exist, " .
                                        "is not a file or is not readable.");
        }
        if (!class_exists('finfo')) {
            throw new Marjory_Exception("Fileinfo extension not present.");
        }
        $fileType  = 'application/octet-stream';
        $fileInfo  = new finfo(FILEINFO_MIME);
        $result    = $fileInfo->file($filePath);
        if (is_string($result) && !empty($result)) {
           $ftype = $result;
        }
        if (in_array($fileType, self::$mimeMap)) {
            $className = self::$mimeMap[$fileType];
            if (!class_exists($className,true)) {
                throw new Marjory_Exception("Extractor class '$className' not found for mimetype '$fileType'");
            }
            return new $className($filePath);
        }
        return false;
    }
}
